package org.youyee.game.object
{
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.utils.getDefinitionByName;
	
	import org.youyee.game.event.MapObjectEvent;
	import org.youyee.game.interfaces.IDepthItem;
	import org.youyee.game.pathFinding.PathNode;
	import org.youyee.game.utils.PositionCalculator;
	
	[Event (name="positionChange", type="org.youyee.game.event.MapObjectEvent")]
	[Event (name="directionChange", type="org.youyee.game.event.MapObjectEvent")]
	[Event (name="itemDestroy", type="org.youyee.game.event.MapObjectEvent")]
	[Event (name="itemModify", type="org.youyee.game.event.MapObjectEvent")]
	[Event (name="itemFocus", type="org.youyee.game.event.MapObjectEvent")]
	
	/**
	 * 存在地图中的物体都应该继承此类 
	 * @author youyee
	 * 
	 */	
	public class MapObject extends Sprite implements IDepthItem
	{
		protected var _zIndex:Number;
		protected var _width:int;
		protected var _height:int;
		protected var _areaSize:int;
		protected var _pathNode:PathNode;
		protected var _direction:int;
		protected var _editable:Boolean;
		
		/**
		 * 皮肤对象 
		 */		
		protected var _skin:MovieClip;
		
		/**
		 * 构造函数 
		 * @param pNode 位置节点
		 * @param objectWidth 物品的宽度
		 * @param objectHeight 物品的高度
		 * 
		 */		
		public function MapObject(pNode:PathNode, objectWidth:int, objectHeight:int)
		{
			super();
			
			_direction = 0;
			this._width = objectWidth;
			this._height = objectHeight;
			this._areaSize = this._width * this._height;
			this._editable = true;
			
			this.mouseChildren = false;
			
			pathNode = pNode;
			
			this.addEventListener(MouseEvent.MOUSE_DOWN, handleObjectFocus);
		}
		
		private function handleObjectFocus(e:MouseEvent):void
		{
			dispatchEvent(new MapObjectEvent(MapObjectEvent.OBJECT_FOCUS));
		}
		
		/**
		 * 设置此物体是否可以允许编辑 
		 * @param value
		 * 
		 */		
		public function set editable(value:Boolean):void
		{
			this._editable = value;
		}
		
		/**
		 * 获取此物体是否可以允许编辑 
		 * 
		 */		
		public function get editable():Boolean
		{
			return this._editable;
		}
		
		/**
		 * 获取皮肤的实例对象 
		 * @return 
		 * 
		 */		
		public function get skinInstance():MovieClip
		{
			return this._skin;
		}
		
		/**
		 * 设置此物体的皮肤 
		 * @param skinClassName 类的名称
		 * 
		 */		
		public function setSkin(skinClassName:String):void
		{
			var c:Class;
			
			try
			{
				c = getDefinitionByName(skinClassName) as Class;
			}
			catch (e:Error){}
			
			if (c)
			{
				removeSkin();
				_skin = new c() as MovieClip;
				addChild(_skin);
			}
		}
		
		/**
		 * 设置物体的方向 
		 * @param value
		 * 
		 */		
		public function set direction(value:int):void
		{
			if (this._direction != value && value >=0 && value < 4)
			{
				if (_direction % 2 != value % 2 && this._width != this._height)
				{
					var t:int = this._width;
					this._width = this._height;
					this._height = t;
				}
				
				this._direction = value;
				
				if (this._skin)
				{
					this._skin.gotoAndStop(value + 1);
				}
				
				dispatchEvent(new MapObjectEvent(MapObjectEvent.DIRECTION_CHANGE));
				dispatchEvent(new MapObjectEvent(MapObjectEvent.OBJECT_MODIFY));
				
				if (this._width != this._height)
				{
					dispatchEvent(new MapObjectEvent(MapObjectEvent.NEED_REFRESH_DEPTH));
				}
			}
		}
		
		/**
		 * 获取物体的方向 
		 * @return 
		 * 
		 */		
		public function get direction():int
		{
			return this._direction;
		}
		
		/**
		 * 旋转物品 
		 * @param clockWise 是否为顺时针旋转（默认顺时针）
		 * 
		 */		
		public function rotationItem(clockWise:Boolean=true):void
		{
			if (clockWise)
			{
				if (this._direction == 3)
				{
					this.direction = 0;
				}
				else
				{
					this.direction++;
				}
			}
			else
			{
				if (this._direction == 0)
				{
					this.direction = 3;
				}
				else
				{
					this.direction--;
				}
			}
		}
		
		/**
		 * 获取深度索引 
		 * @return 
		 * 
		 */		
		public function get zIndex():Number
		{
			return this._zIndex;
		}
		
		/**
		 * 设置位置节点 
		 * @param value
		 * 
		 */		
		public function set pathNode(value:PathNode):void
		{
			//这里本来加入 value != this._pathNode 但是考虑到拖拽进出场景可能遇到的问题，这里去掉了个判断
			if (value)
			{
				this._pathNode = value;
				PositionCalculator.setObjectPositionByPathNode(this, value);
				updateZIndexByPathNode(value);
				
				dispatchEvent(new MapObjectEvent(MapObjectEvent.POSTION_CHANGE));
				dispatchEvent(new MapObjectEvent(MapObjectEvent.NEED_REFRESH_DEPTH));
				dispatchEvent(new MapObjectEvent(MapObjectEvent.OBJECT_MODIFY));
			}
		}
		
		/**
		 * 通过给入的节点更新z轴索引 
		 * @param pNode 地图节点
		 * 
		 */
		protected function updateZIndexByPathNode(pNode:PathNode):void
		{
			this._zIndex = pNode.x + pNode.y;
		}
		
		/**
		 * 获取位置节点 
		 * @return 
		 * 
		 */		
		public function get pathNode():PathNode
		{
			return this._pathNode;
		}
		
		/**
		 * 获取物品的宽度 
		 * @return 
		 * 
		 */		
		public function get itemWidth():int
		{
			return this._width;
		}
		
		/**
		 * 获取物品的高度 
		 * @return 
		 * 
		 */		
		public function get itemHeight():int
		{
			return this._height;
		}
		
		/**
		 * 获取面积的尺寸 
		 * @return 
		 * 
		 */		
		public function get areaSize():int
		{
			return _areaSize;
		}
		
		/**
		 * 销毁物体  
		 * 
		 */		
		public function destroy():void
		{
			this._pathNode = null;
			removeSkin();
			
			//移除所有可能的显示对象
			while (numChildren)
			{
				removeChild(this.getChildAt(0));
			}
			
			dispatchEvent(new MapObjectEvent(MapObjectEvent.OBJECT_DESTROY));
		}
		
		/**
		 * 移除皮肤 
		 * 
		 */		
		protected function removeSkin():void
		{
			if (this._skin)
			{
				if (this._skin.parent)
				{
					this._skin.parent.removeChild(this._skin);
				}
				
				//尝试调用销毁方法
				if ("destroy" in this._skin)
				{
					this._skin["destroy"]();
				}
				
				//这里考虑在一般情况下和后面的while循环功能重复，所以先注释
				/*if (this.skin.parent)
				{
				this.skin.parent.removeChild(this.skin);
				}*/
			}
			
			this._skin = null;
		}
		
		/**
		 * 判断物品是否有此节点 
		 * @param testMapObject 需要被测试的物体
		 * @param node 位置节点
		 * @return 判断结果
		 * 
		 */		
		public static function objectHasPathNode(testMapObject:MapObject, node:PathNode):Boolean
		{
			var p:PathNode = testMapObject.pathNode;
			
			var startX:int = p.x;
			var startY:int = p.y;
			
			var endX:int = p.x + testMapObject.itemWidth - 1;
			var endY:int = p.y + testMapObject.itemHeight - 1;
			
			if (node.x >= startX && node.x <= endX && node.y >= startY && node.y <= endY)
			{
				return true;
			}
			
			return false;
		}
		
		/**
		 * 判断物品是否存在节点集合中的某一个节点 
		 * @param testMapobject 需要被测试的物体
		 * @param nodes 节点集合
		 * @return 判断结果
		 * 
		 */		
		public static function objectHasPathNodes(testMapobject:MapObject, nodes:Array):Boolean
		{
			var len:int = nodes.length;
			
			for (var i:int=0; i<len; ++i)
			{
				if (objectHasPathNode(testMapobject, nodes[i] as PathNode))
				{
					return true;
				}
			}
			
			return false;
		}
	}
}